package com.yx.filesystem.storage;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SocketServer extends Thread {
	public static int BUFFER_SIZE = 1024*1024;
	public static int SOCKET_BUFFER_SIZE = 1024*1024;
	public static int THREAD_PPPL_SIZE = Runtime.getRuntime().availableProcessors() * 5;
	ExecutorService executorService = Executors.newFixedThreadPool(THREAD_PPPL_SIZE);
	int port = 9997;
	ServerSocket serverSocket = null;

	public SocketServer(int port) throws Exception {
		this.port = port;
		serverSocket = new ServerSocket(port);
		serverSocket.setReceiveBufferSize(SOCKET_BUFFER_SIZE); 
		this.start();
		System.out.println("FileSystem Server ("+THREAD_PPPL_SIZE+" processing Thread) is started! Listening port:"+port);
	}

	public void run() {
		while (true) {
			try {
				Socket socket = serverSocket.accept();
				executorService.execute(new SocketInvoker(socket));				
			} catch (Throwable e) {
				//e.printStackTrace();
			}
		}
	}

	public class SocketInvoker implements Runnable {
		Socket socket = null;

		public SocketInvoker(Socket socket) {
			this.socket = socket;			
		}

		public void run() {
			BufferedInputStream socketInput=null;
			BufferedOutputStream socketOutput=null;
			try{
				socket.setSendBufferSize(SOCKET_BUFFER_SIZE);
				socket.setTrafficClass(0x08|0x10);
				socketInput = new BufferedInputStream(socket.getInputStream());
				socketOutput = new BufferedOutputStream(socket.getOutputStream());
				Transport transport = new Transport(socketInput);
				SocketHandler handler = SocketHandler.get(transport.getHandler());
				handler.handler(socketInput,socketOutput, transport);
			}catch(Throwable e){
				//e.printStackTrace();
				error(socketOutput,e);
			}finally{
				try{
					if(socketInput!=null)socketInput.close();
				}catch(Throwable e){					
				}
				try{
					if(socketOutput!=null)socketOutput.close();
				}catch(Throwable e){					
				}
				try{
					if(socket!=null)socket.close();
				}catch(Throwable e){					
				}
			}
			
		}
		public void error(BufferedOutputStream socketOutput,Throwable e){
			try {
				if(socketOutput!=null){
					Transport transport = new Transport(null, false,e.getMessage(), null);
					transport.write(socketOutput);
				}
			} catch (Throwable ex) {
			}
		}

	}
}
